package cn.tedu.mall.front.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.front.service.IFrontCategoryService;
import cn.tedu.mall.pojo.front.entity.FrontCategoryEntity;
import cn.tedu.mall.pojo.front.vo.FrontCategoryTreeVO;
import cn.tedu.mall.pojo.product.vo.CategoryStandardVO;
import cn.tedu.mall.product.service.front.IForFrontCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.logging.Handler;

@DubboService
@Service
@Slf4j //提供log对象
public class FrontCategoryServiceImpl implements IFrontCategoryService {
    //Redis的key，定义成常量
    public static final String CATEGORY_TREE_KEY="category:tree";
    @Autowired
    private RedisTemplate redisTemplate;
    //从数据库中查询分类信息，通过dubbo调用product服务实现的
    @DubboReference
    private IForFrontCategoryService dubboCategoryService;

    @Override
    public FrontCategoryTreeVO categoryTree() {
        //1.需要判断redis中是否有分类信息
        if(redisTemplate.hasKey(CATEGORY_TREE_KEY)){
            //redis中有分类信息，直接返回
            FrontCategoryTreeVO<FrontCategoryEntity> frontCategoryTreeVO =
                    (FrontCategoryTreeVO<FrontCategoryEntity>) redisTemplate.boundValueOps(CATEGORY_TREE_KEY).get();
        }
        //代码走到这里说明没有数据
        //2.从数据库中查询所有分类信息
        List<CategoryStandardVO> categoryStandardVOS = dubboCategoryService.getCategoryList();
        //3.构建分类信息的三级树结构
        FrontCategoryTreeVO<FrontCategoryEntity> treeVO = initTree(categoryStandardVOS);
        //4.保存到redis中
        redisTemplate.boundValueOps(CATEGORY_TREE_KEY).set(treeVO,30, TimeUnit.DAYS);
        //记得返回treeVO对象
        return treeVO;
    }


    private FrontCategoryTreeVO<FrontCategoryEntity> initTree(List<CategoryStandardVO> categoryStandardVOS) {
        //第一部分：确定所有分类对象的父对象
        //parent_id-->子id(多个)    声明一个map，使用父id作为key，使用子分类类型的集合作为value
        Map<Long,List<FrontCategoryEntity>> map = new HashMap<>();
        log.info("当前分类对象的总和为:",categoryStandardVOS.size());
        //遍历categoryStandardVOS
        for (CategoryStandardVO categoryStandardVO : categoryStandardVOS) {
            //需要将categoryStandardVO对象转成FrontCategoryEntity
            FrontCategoryEntity frontCategoryEntity = new FrontCategoryEntity();
            BeanUtils.copyProperties(categoryStandardVO,frontCategoryEntity);
            //获取父id，根据父id做为map的key
            Long parentId = frontCategoryEntity.getParentId();
            //先判断map中是否有该父id作为key的值
            if (map.containsKey(parentId)){
                //如果有这个key，直接添加到value的集合中
                map.get(parentId).add(frontCategoryEntity);
            } else {
                //如果没有这个key，需要创建key以及value(list)
                List<FrontCategoryEntity> value = new ArrayList<>();
                value.add(frontCategoryEntity);
                //使用当前parentId做为map中的key，List类型的value对象作为map中value
                map.put(parentId,value);
            }
        }
        //第二部分:将子分类对象关联到父分类包含的children属性中
        //从map中的根分类开始，通过循环遍历每个级别的分类对象，添加到对应的级别的children属性中
        //从一级分类开始，顶级父类，程序设计中顶级父类的父id是0
        List<FrontCategoryEntity> firstLevels = map.get(0L);
        //判断firstLevels是否为空，为空直接抛出异常
        if(firstLevels==null)
            throw new CoolSharkServiceException(ResponseCode.INTERNAL_SERVER_ERROR,"当前项目没有根分类");
        //遍历一级集合
        for (FrontCategoryEntity firstLevel : firstLevels) {
           //获取一级分类的id，一级分类id是二级分类的父id
            Long secondLevelParentId = firstLevel.getId();
            //获取二级分类集合
            List<FrontCategoryEntity> secondLevels = map.get(secondLevelParentId);
            //判断二级分类集合是否为空，为空结束本次循环
            if (secondLevels==null){
                log.info("当前分类缺少二级分类对象,{}",firstLevel);
                continue;
            }
            //遍历二级分类集合
            for (FrontCategoryEntity secondLevel : secondLevels) {
                //获取二级分类的id，作为三级分类的父id
                Long thirdLevelParentId = secondLevel.getId();
                //获取三级分类集合
                List<FrontCategoryEntity> thirdLevels = map.get(thirdLevelParentId);
                //判断三级分类集合是否为空，为空结束本次循环
                if(thirdLevels==null){
                    log.info("当前分类缺少三级分类对象,{}",secondLevel);
                    continue;
                }
                //将三级集合添加到二级分类对象的children属性
                secondLevel.setChildrens(thirdLevels);
            }
            //将二级集合添加到一级集合的children属性中
            firstLevel.setChildrens(secondLevels);
        }
        //到此为止，所有分类对象的父子关系已经构建完成
        //返回值类型是FrontCategoryTreeVO<FrontCategoryEntity>
        FrontCategoryTreeVO<FrontCategoryEntity> treeVO = new FrontCategoryTreeVO<>();
        //将一级分类集合添加到该对象的categories属性中
        treeVO.setCategories(firstLevels);
        return treeVO;
    }
}
